import numpy as np

class Func:
    #
    def evaluate(self, X):
        """
        Вычисляет значения функции на массиве значений.
        X: массив значений
        Возвращает: массив значений функции
        """
        pass
    #
    def derivative(self, X):
        """
        Вычисляет значения производной функции f'(x) на массиве значений.
        X: массив значений
        Возвращает: массив значений производной фунции
        """
        pass
    #
    def derivative2(self, X):
        """
        Вычисляет значения 2-й производной функции f''(x) на массиве значений.
        X: массив значений
        Возвращает: массив значений 2-й производной фунции
        """
        pass
    #
    def derivative_div_x(self, X):
        """
        Вычисляет значения производной функции f'(x)/x на массиве значений.
        X: массив значений
        Возвращает: массив значений 2-й производной фунции
        """
        pass

class Square(Func):
    #
    def evaluate(self, X):
        return 0.5 * X * X
    #
    def derivative(self, X):
        return X
    #
    def derivative2(self, X):
        return np_ones_like(X)
    #
    def derivative_div_x(self, X):
        return np_ones_like(X)

class SoftAbs(Func):
    #
    def __init__(self, eps=0.001):
        self.eps = eps
    #
    def evaluate(self, X):
        eps = self.eps
        return np.sqrt(X*X + eps*eps) - eps
    #
    def derivative(self, X):
        eps = self.eps
        return X / np.sqrt(X*X + eps*eps)
    #
    def derivative_div_x(self, X):
        eps = self.eps
        return 1 / np.sqrt(X*X + eps*eps)

class Hinge(Func):
    #
    def __init__(self, d=0):
        self.d = d
    #
    def evaluate(self, X):
        V = np.zeros_like(X)        
        np.putmask(V, X < self.d, self.d - X)
        return V
    #
    def derivative(self, X):
        G = np.zeros_like(X)
        np.putmask(G, X < self.d, -1)
        return G
